// SPDX-FileCopyrightText: 2022-2025 CASTest Corporation Limited
// SPDX-FileCopyrightText: 2022-2025 Institute of Computing Technology, Chinese Academy of Sciences
// SPDX-License-Identifier: LGPL-v3

#ifndef SIMULATION_H
#define SIMULATION_H

#include "FaultList.h"
#include "STILparser.h"
#include "LevelEventContainer.h"
#include "Patterns.h"
#include "Value.h"
#include "Threading.h"

class Simulation : public FaultList {

public:
    Simulation() {
        _thread_pool = new ThreadPool;
    };

    ~Simulation() {};

    void ParseStilFile(const string& stil_file);

    void GetSerialPattern();
    void GetParallelPattern();

    bool SingleFaultSim(vector<Fault *> &fsimlist, EventContainer *events,
                        size_t start_faults_id, size_t end_faults_id);

    void ConstructDffMater(int num_word);


    bool CompareLogicSimPo(const vector<vector<Value>> &serial_patterns_po,
                           size_t pattern_id, size_t logic_array_id);

    bool CompareLogicSimScanChain(const vector<vector<vector<Value>>> &unload_values,
                                  size_t pattern_id, size_t logic_array_id);

    void AllocLogicArray(int num_pattern);

    bool LogicSim(size_t start_pattern_id, size_t end_pattern_id, EventContainer *events);

    void PrintSerialScanChainsValue(size_t pattern_id, size_t frame_id);

    bool EvalGateFSim(Gate *gptr, int word_id, int frame_id,
                      EventContainer *events, vector<bool> &fault_mark,
                      vector<Value> &fault_array, vector<bool>& dff_master_mark, vector<Value> &dff_master_value);

    bool UpdateFsimGateValue(Gate* gptr, Value new_value, size_t word_id,
                             int frame_id ,vector<Value>& fault_array,
                             vector<bool> &fault_mark,  EventContainer* events);


protected:
    //Multi-thread.
    unordered_map<thread::id, int> _thread_id;
    mutex       _mutex;
    ThreadPool* _thread_pool;

    // parallel sim
    int     _num_word;
    int     _total_process_fault;
    // serial sim
    int     _num_pattern;
    int     _pi_value_size;
    int     _last_pattern_bit_num;
    bool    _is_parallel_pattern;
    Patterns    _pattern_reader;
    vector<vector<vector<Value>>> _unload_value;
    vector<vector<vector<Value>>> _load_value;
    vector<vector<Value>> _pi_value;
    vector<vector<Value>> _po_value;
    vector<vector<Value>> _pattern_clock_value;
    //Data structures of fault-free simulation.
    // 1st dim represent diff gate
    // the serial logic simulation 2nd dim represent different pattern
    // the parallel logic simulation 2nd dim represent different word
    // the 3rd dim represent different frame
    vector<vector<vector<Value>>>   _logic_array;
    // represent the gate value store which frame
    vector<vector<vector<int>>>     _gate_value_array_frame_ids;
//    vector<vector<Value>> _logic_array;
    // dff master slave structe
    // store dff master value
    // 1st dim represent dff master
    vector<vector<Value>>           _dff_master_logic_array;


    // serial logic simualtion the word_id represent patter id
    // parallel logic simulation the word_id represent word
    void AddActiveGateToEvents(Gate *gptr, EventContainer *events, int word_id);

    // serial logic simulation the word_id represenr pattern id
    void UpdateGateValue(Gate *gptr, int word_id, int frame_id, Value &new_value, EventContainer *events);

    // serial logic simulation the word_ids only contain one pattern id
    void EvalGateSim(Gate *gptr, const vector<int> &word_ids, int frame_id ,EventContainer *events);

    // set  patterns to logic array
    void SetPattern(const vector<vector<Value>> &serial_patterns, const vector<vector<vector<Value>>> &load_values,
                    EventContainer *events, size_t pattern_id, size_t logic_array_id);

    vector<int> _clock_pi_ids;

};

#endif // SIMULATION_H
